package com.augurit.wf.mgmt.web;

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;

import javax.imageio.ImageIO;

import org.apache.struts2.convention.annotation.Result;
import org.apache.struts2.convention.annotation.Results;
import org.jbpm.api.ProcessDefinition;
import org.jbpm.api.ProcessInstance;
import org.jbpm.api.model.Activity;
import org.jbpm.api.model.ActivityCoordinates;
import org.jbpm.pvm.internal.model.ActivityImpl;
import org.jbpm.pvm.internal.model.ProcessDefinitionImpl;
import org.springframework.beans.factory.annotation.Autowired;

import sun.misc.BASE64Decoder;

import com.augurit.common.base.action.BaseAction;
import com.augurit.common.base.action.CrudActionSupport;
import com.augurit.common.base.action.ExtBaseAction;
import com.augurit.common.base.form.Attachment;
import com.augurit.common.util.FileUtils;
import com.augurit.wf.bi.service.IWfBusTemplateService;
import com.augurit.wf.bi.web.form.WfBusTemplateForm;
import com.augurit.wf.common.extmodel.ExtTreeNodeFactory;
import com.augurit.wf.common.extmodel.ProcessReleaseTreeNode;
import com.augurit.wf.common.extmodel.ProcessVersionTreeNodeFactory;
import com.augurit.wf.common.service.IWfService;
import com.augurit.wf.common.util.WfUtils;
import com.augurit.wf.mgmt.convert.ConvertToExtModel;
import com.augurit.wf.mgmt.web.form.WfProcessInstanceForm;
import com.augurit.wf.mgmt.web.form.WfProcessReleaseForm;
import com.augurit.wf.mgmt.web.form.WfProcessVersionForm;
import com.opensymphony.xwork2.ModelDriven;
import com.opensymphony.xwork2.Preparable;

/**
 * 流程发布管理
 *
 */

@SuppressWarnings("serial")
@Results({
	@Result(name = CrudActionSupport.RELOAD, location = "wf-process-release.action", type = "redirect")//,
	//@Result(name = CrudActionSupport.SUCCESS, location = "/wf/mgmt/process-deploy/process-deploy.jsp"),
	//@Result(name = WfProcessReleaseAction.PROCESS_NODE_INFO, location = "/wf/mgmt/process-deploy/process-node-detail.jsp"),
	//@Result(name = WfProcessReleaseAction.VERSION_NODE_INFO, location = "/wf/mgmt/process-deploy/version-node-detail.jsp"),
	//@Result(name = WfProcessReleaseAction.VIEW_PROCESS_INSTANCE, location = "/wf/view-process-diagram.jsp")
})
public class WfProcessReleaseAction extends ExtBaseAction implements ModelDriven<WfProcessReleaseForm>, Preparable {
	
	public static final String PROCESS_NODE_INFO = "proces_node_info";		//流程节点对应的详细信息
	public static final String VERSION_NODE_INFO = "version_node_info";		//流程版本节点对应的详细信息
	public static final String VIEW_PROCESS_INSTANCE = "view_process_instance";	//流程实例对应的流程图（标识所处节点）
	
	@Autowired
	private IWfService wfService;
	
	@Autowired
	private IWfBusTemplateService wfBusTemplateService;
	
	private ExtTreeNodeFactory factory = new ProcessVersionTreeNodeFactory();
	
	private WfProcessReleaseForm form;
	
	private String loadProcessDiagramUrl;
	
	private String processDefXmlFile;//流程图的XML
	private String imageBase64;//流程图的base64格式
	private Long templateId;//模块ID
	private Long taskInstDbid;//任务DBID
	
	public String list() throws Exception{
		return SUCCESS;
	}
	
	/**
	 * 展开流程版本树
	 * @return
	 * @throws Exception
	 */
	public String expandProcessVersionTree() throws Exception{
		String type = BaseAction.getRequest().getParameter("type");
		String value = BaseAction.getRequest().getParameter("value");
		
		ProcessReleaseTreeNode processVersionTreeNode = factory.createTreeNode(type, value);
		List<ProcessReleaseTreeNode> nodes = processVersionTreeNode.getChildNodes(wfService);
		ExtBaseAction.extRenderListJson(nodes, false);
		return null;
	}
	
	/**
	 * 获取流程的版本
	 * @return
	 * @throws Exception
	 */
	public String getVersionListInProcess() throws Exception{
		List<ProcessDefinition> list = wfService.getProcDefByProcDefKey(form.getProcessDefKey());
		List<WfProcessVersionForm> nodes = ConvertToExtModel.convertProcVerListToFormList(list);
		ExtBaseAction.extRenderListJson(nodes, true);
		return null;
	}
	
	/**
	 * 发布xml文件定义的流程版本
	 * @return
	 * @throws Exception
	 */
	public String realseXmlProcessDefFile() throws Exception{
		try{
			List<Attachment> attachments = this.getAttachmentList();
			String deploymentId = ""; 
			if(attachments != null && attachments.size() > 0){
				for(Attachment attachment:attachments){
					deploymentId = wfService.deployByXmlFileFromAttachment(attachment);
				}
				//导入权限
				ProcessDefinitionImpl curProcessDef = (ProcessDefinitionImpl)wfService.getProcDefByDeploymentId(deploymentId);
				//更新模板的版本并导入权限
				wfBusTemplateService.updateVersionAndImportPriv(wfService, templateId, curProcessDef);
				
				renderHtml("{'success':true, 'processName':" + "'" + curProcessDef.getName() + "'}");
			}
			else{
				renderHtml("{'success':false}");
			}
		}
		catch(Exception e){
			e.printStackTrace();
			renderHtml("{'success':false}");
		}

		return null;
	}
	
	/**
	 * 级联删除流程版本（删除指定的流程版本其对应的流程实例）
	 * @return
	 * @throws Exception
	 */
	public String deleteProcessVersionCascade() throws Exception{
		wfService.deleteProcessVersionCascade(form.getProcessDefKey(), form.getProcessVersion());
		ExtBaseAction.extRenderSuccess();
		return null;
	}
	
	/**
	 * 根据流程设计器传送的XML和image发布流程定义文件
	 * @return
	 * @throws Exception
	 */
	@SuppressWarnings({ "deprecation", "static-access" })
	public String realseProcessDefFileByXmlAndImage() throws Exception{
		
		try {
			//创建临时保存当前流程XML和图片文件的目录
			String tempDir = getRequest().getRealPath("/") + "\\temp";
			File tempFile = new File(tempDir);
			if(!tempFile.exists())
				tempFile.mkdir();
			
			//把XML和图片压缩到ZIP中
			File zipFile = new File(tempDir+"\\process.zip");
			ZipOutputStream zipOut = new ZipOutputStream(new FileOutputStream(zipFile));
			zipOut.putNextEntry(new ZipEntry("processDefXml.jpdl.xml"));
			zipOut.write(this.getProcessDefXmlFile().getBytes("GBK"));
			zipOut.flush();
			
			zipOut.putNextEntry(new ZipEntry("processDefImage.png"));
			byte[] imageBytes = new BASE64Decoder().decodeBuffer(this.getImageBase64());
			zipOut.write(imageBytes);
			zipOut.flush();
			
			zipOut.closeEntry();
			zipOut.close();
			
			//发布流程
			String deploymentId = wfService.deployByZipFileByZipInputStream(new ZipInputStream(new FileInputStream(tempDir+"\\process.zip")));
			ProcessDefinitionImpl curProcessDef = (ProcessDefinitionImpl)wfService.getProcDefByDeploymentId(deploymentId);
			
			//更新模板的版本并导入权限
			wfBusTemplateService.updateVersionAndImportPriv(wfService, templateId, curProcessDef);
			
			
			//删除临时的ZIP文件
			zipFile.delete();
			
			//构造输出到客户端的信息
			form.setProcessDefKey(curProcessDef.getKey());
			form.setProcessVersion(curProcessDef.getVersion());
			form.setReleaseResult(true);
			form.setProcessDefXmlFile(null);
			
			String resultStr = this.renderXml(form,"resultss",WfProcessReleaseForm.class);
			renderXml(resultStr);
		} catch (Exception e) {
			form.setReleaseResult(false);
			String resultStr = this.renderXml(form,"result",WfProcessReleaseForm.class);
			renderXml(resultStr);
			e.printStackTrace();
		}
		
		return null;
	}
	
	/**
	 * 发布zip流程定义文件
	 * @return
	 * @throws Exception
	 */
	public String realseZipProcessDefFile() throws Exception{
		try{
			List<Attachment> attachments = this.getAttachmentList();
			
			String deploymentId = ""; 
			if(attachments != null && attachments.size() == 1){
				deploymentId = wfService.deployByZipFileFromAttachment(attachments.get(0));
				
				//导入权限
				ProcessDefinitionImpl curProcessDef = (ProcessDefinitionImpl)wfService.getProcDefByDeploymentId(deploymentId);
				//更新模板的版本并导入权限
				wfBusTemplateService.updateVersionAndImportPriv(wfService, templateId, curProcessDef);
				
				renderHtml("{'success':true, 'processName':" + "'" + curProcessDef.getName() + "'}");
			}
			else{
				renderHtml("{'success':false}");
			}
			
		}
		catch(Exception e){
			e.printStackTrace();
			renderHtml("{'success':false}");
		}
		
		return null;
	}
	
	/**
	 * 获取流程结点信息
	 * @return
	 * @throws Exception
	 */
	public String getProcessNodeInfo() throws Exception{
		return PROCESS_NODE_INFO;
	}
	
	/**
	 * 获取版本节点信息
	 * @return
	 * @throws Exception
	 */
	public String getVersionNodeInfo() throws Exception{
		return VERSION_NODE_INFO;
	}
	
	/**
	 * 获取流程定义文件
	 * @return
	 * @throws Exception
	 */
	public String loadProcessDefXmlFile() throws Exception{
		//获取指定流程定义.jpdl.xml文件对应的Stream资源
		InputStream in = wfService.getProcDefXmlFileAsStream(form.getProcessDefKey(), form.getProcessVersion());
		if(in != null){
			form.setProcessDefXmlFile(FileUtils.convertInputStreamToString(in));
		}
		ExtBaseAction.extRenderFormJson(form);
		return null;
	}
	
	/**
	 * 获取流程定义文件，并以XML形式输出到客户端
	 * @return
	 * @throws Exception
	 */
	@SuppressWarnings("static-access")
	public String loadProcessDefXmlFileOutToXml() throws Exception{
		//初始化流程版本和KEY
		if(form.getProcessInstanceId() != null){
			String[] processDefId = wfService.getProcessDfIdByProcessInstenceId(form.getProcessInstanceId()).split("-");
			form.setProcessDefKey(processDefId[0]);
			form.setProcessVersion(new Integer(processDefId[1]));
		}else if(taskInstDbid != null){
			ProcessDefinitionImpl processDefinitionImpl = wfService.getProcDefByTaskInstDbid(taskInstDbid);
			form.setProcessDefKey(processDefinitionImpl.getKey());
			form.setProcessVersion(new Integer(processDefinitionImpl.getVersion()));
		}else if(form.getProcessDefId() != null){
			String[] processDefId = form.getProcessDefId().split("-");
			form.setProcessDefKey(processDefId[0]);
			form.setProcessVersion(new Integer(processDefId[1]));
		}
		
		//获取指定流程定义.jpdl.xml文件对应的Stream资源
		InputStream in = wfService.getProcDefXmlFileAsStream(form.getProcessDefKey(), form.getProcessVersion());
		if(in != null){
			this.renderXml(FileUtils.convertInputStreamToString(in));
		}
		
		return null;
	}
	
	
	/**
	 * 获取流程实例
	 * @return
	 * @throws Exception
	 */
	public String getProcessInstance() throws Exception {
		List<ProcessInstance> list = wfService.getAllProcessInstances(form.getProcessDefKey(), form.getProcessVersion());
		
		List<WfProcessInstanceForm> results = ConvertToExtModel.convertToProcessInstanceList(list);
		ExtBaseAction.extRenderGridJson(results);
		return null;
	}
	
	public void prepare() throws Exception {
		prepareModel();
	}
	
	/**
	 * 准备页面模型
	 */
	protected void prepareModel() throws Exception {
		form = new WfProcessReleaseForm();
	}
	

	public WfProcessReleaseForm getModel() {
		return form;
	}

	public String getLoadProcessDiagramUrl() {
		return loadProcessDiagramUrl;
	}

	public void setLoadProcessDiagramUrl(String loadProcessDiagramUrl) {
		this.loadProcessDiagramUrl = loadProcessDiagramUrl;
	}

	public String getProcessDefXmlFile() {
		return processDefXmlFile;
	}

	public void setProcessDefXmlFile(String processDefXmlFile) {
		this.processDefXmlFile = processDefXmlFile;
	}

	public String getImageBase64() {
		return imageBase64;
	}

	public void setImageBase64(String iamgeBase64) {
		this.imageBase64 = iamgeBase64;
	}

	public WfProcessReleaseForm getForm() {
		return form;
	}

	public void setForm(WfProcessReleaseForm form) {
		this.form = form;
	}

	public Long getTemplateId() {
		return templateId;
	}

	public void setTemplateId(Long templateId) {
		this.templateId = templateId;
	}

	public Long getTaskInstDbid() {
		return taskInstDbid;
	}

	public void setTaskInstDbid(Long taskInstDbid) {
		this.taskInstDbid = taskInstDbid;
	}
}
